/**
 * This javascript file handles map initialization and events.
 * 
 * @author	Tobin Bradley
 * @license 	MIT
 */


/**
 * Globals specifically for OpenLayers Use
 */
var markerLayer = null;  // Layer for vector markers
var selectControl = null;  // OpenLayers select control for vector marker layer

/**
 * Fix for OpenLayers using 900913 for web mercator and AGS using 102113
 * Specify projection for AGS as 102113 and it will substitute that rather
 * than use 900913 for those requests.
 * Must run before map init
 */ 
OpenLayers.Layer.WMS.prototype.getFullRequestString = function(newParams,altUrl)
{
    try{
        var projectionCode=typeof this.options.projection == 'undefined' ? this.map.getProjection() : this.options.projection;
    }catch(err){
        var projectionCode=this.map.getProjection();
    }
    this.params.SRS = projectionCode=="none" ? null : projectionCode;
    return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);
}

OpenLayers.IMAGE_RELOAD_ATTEMPTS = 4;  // Avoid pink tiles

/**
 * Map Initialization
 * Note most of the varible items - map config, layers, initial extent, etc.,
 * are in geoportal-settings.js
 */
function initializeMap(){
	// Set options and initialize map

	
	var mapOptions = {
		projection: new OpenLayers.Projection("EPSG:900913"),
		displayProjection: new OpenLayers.Projection("EPSG:4326"),
		units: "m",
		numZoomLevels: 18,
		maxResolution: 156543.0339,
		maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34),
		restrictedExtent: new OpenLayers.Bounds(defaultMapExtent[0],defaultMapExtent[1],defaultMapExtent[2],defaultMapExtent[3]),
		controls: [new OpenLayers.Control.Navigation()],
		fallThrough: false
	};
   	
	map = new OpenLayers.Map('map', mapOptions);  
	
	
	// Add layers
	$.each(mapLayers, function(index, value) {
          if (value.wmsurl.indexOf("{x}") != -1) {  //tiles
			var layer = new OpenLayers.Layer.XYZ (
				value.name,
				value.wmsurl
			);
			map.addLayer(layer);
			
		}
		else {  //wms
			var layer = new OpenLayers.Layer.WMS(
				value.name,
				value.wmsurl,
				{
					layers: value.layers,
					format: value.format,
					transparent: value.transparent
				},{
					isBaseLayer: value.isBaseLayer,
					opacity: value.opacity,
					visibility: value.isVisible,
					minScale: value.minScale,
					maxScale: value.maxScale,
					attribution: value.attribution
					
				}
			);
			map.addLayer(layer);
			
			
		}
     });
	
	// Map toolbar
	$("#mapcontrols").buttonset();
	$("#zoom_previous").button({ icons: { primary: 'ui-icon-arrowthickstop-1-w' }, text: false });
	$("#zoom_next").button({ icons: { primary: 'ui-icon-arrowthickstop-1-e' }, text: false });
	$("#mapcontrols input:radio").click( function() { toggleControl($(this)) });
	$("#zoom_previous").click( function() { nav.previousTrigger() });
	$("#zoom_next").click( function() { nav.nextTrigger() });
	$("#toolbar").fadeIn("slow");
	
	
	// Vector Marker Layer
	var styleMap = new OpenLayers.StyleMap({
		fillOpacity: 1,
		pointRadius: 18
	});
	// images for vector marker layer
	// 0=selected, 1=facility, 2=identify
	var lookup = {
		0: {externalGraphic: "img/red-dot-marker.png", backgroundGraphic: "img/marker_shadow.png", graphicYOffset: -30, backgroundXOffset: 0, backgroundYOffset: -25 },
		1: {externalGraphic: "img/blue-marker.png", backgroundGraphic: "img/marker_shadow.png", graphicYOffset: -30, backgroundXOffset: 0, backgroundYOffset: -25 }
	}
	styleMap.addUniqueValueRules("default", "type", lookup);
	markerLayer = new OpenLayers.Layer.Vector('Map Markers', {
		styleMap: styleMap, displayInLayerSwitcher: false
	});
	map.addLayer(markerLayer);
	
	
	// Map Controls
	map.addControl(new OpenLayers.Control.PanZoomBar());
	map.addControl(new OpenLayers.Control.Scale());
	map.addControl(new OpenLayers.Control.MousePosition({'div': OpenLayers.Util.getElement('toolbar-coords')}));
	map.addControl(new OpenLayers.Control.LayerSwitcher({'div':OpenLayers.Util.getElement('layerswitcher'), roundedCorner: false}));		
	map.addControl(new OpenLayers.Control.Permalink());
	map.addControl(new OpenLayers.Control.ScaleLine());
	map.addControl(new OpenLayers.Control.Graticule({ numPoints: 2, labelled: true, visible: false }));
	
	
	mapControls = {
		measure: new OpenLayers.Control.Measure(
			OpenLayers.Handler.Path, {
			persist: true, geodesic: true, displaySystem: 'english'
			}
		),
		identify: new OpenLayers.Control.Click(
			{title:"Identify"}
		)
	}

	var control;
	for(var key in mapControls) {
		control = mapControls[key];
		control.events.on({
			"measure": handleMeasurements,
			"measurepartial": handleMeasurements
		});
		map.addControl(control);
	}
	
	// Add selection control for marker layer
	selectControl = new OpenLayers.Control.SelectFeature(markerLayer,
                {onSelect: onFeatureSelect, onUnselect: onFeatureUnselect, stopSingle: true});
	map.addControl(selectControl);
	selectControl.activate(); 
	
    
	// Opacity control and dropdown
	$('#opacitySlider').slider({range: "min", min: .1, max: 1, step: .05, value: .5, slide: function(event, ui) {
			map.layers[$('#opacitydll').val()].setOpacity(ui.value);
			$("#layerOpacity").html("Layer Opacity: " + parseInt(ui.value * 100 ) + "%");
		}
	});
	for (var i=0; i<map.layers.length; i++) {
		if (!map.layers[i].isBaseLayer && map.layers[i].name != "Map Markers") {
			$('#opacitydll').append('<option value="' + i + '">' + map.layers[i].name + '</option>');  
		}
	}

    
	// Zoom to Initial Extent
	// if localstorage and saved coords, zoom there
	if (window.localStorage) {
		if (localStorage.getItem('gp_lastSelected_longitude') && localStorage.getItem('gp_lastSelected_latitude')) {
			zoomToLonLat(localStorage.getItem('gp_lastSelected_longitude'), localStorage.getItem('gp_lastSelected_latitude'), 8);
			locationFinder("Address", 'master_address_table', 'objectid', localStorage.getItem('gp_lastSelected'));
		}
		else {
			if (!map.getCenter()) {
				map.zoomToExtent(new OpenLayers.Bounds(defaultMapExtent[0],defaultMapExtent[1],defaultMapExtent[2],defaultMapExtent[3]));
			}
		}
	}
	else {
		if (!map.getCenter()) {
			map.zoomToExtent(new OpenLayers.Bounds(defaultMapExtent[0],defaultMapExtent[1],defaultMapExtent[2],defaultMapExtent[3]));
		}
	}

}


// Toggle Map Controls
function toggleControl(element) {
	for(key in mapControls) {
		var control = mapControls[key];
		if( $(element).attr("value") == key ) {
			control.activate();
		} else {
			control.deactivate();
		}
	}
}


// Handle Measurements
function handleMeasurements(event) {
	var geometry = event.geometry;
	var units = event.units;
	var order = event.order;
	var measure = event.measure;
	if(order == 1) {
		$("#toolbar-length").html("Length: " + measure.toFixed(3) + " " + units);
	} else {
		$("#toolbar-area").html("Area: " + measure.toFixed(3) + " " + units + "<sup>2</" + "sup>");
	}

}


/**
 * Zoom to a latlong at a particular zoom level. Projects wgs84 to 900913
 * @param {float} long
 * @param {float} lat
 * @param {integer} zoom
 */
function zoomToLonLat (lon, lat, zoom) {
	point = new OpenLayers.Geometry.Point(lon, lat);
	OpenLayers.Projection.transform(point, map.displayProjection, map.getProjectionObject()); 
	map.setCenter(new OpenLayers.LonLat(point.x, point.y), zoom);
}


/**
 * Zoom to a latlong at a particular zoom level
 * @param {float} long
 * @param {float} lat
 * @param {integer} zoom
 */
function zoomTo (x, y, zoom) {
	map.setCenter(new OpenLayers.LonLat(x, y), zoom);
}


/* Marker Vector Layer Popups */
function onPopupClose(evt) {
	selectControl.unselectAll();
}
function onFeatureSelect(feature) {
	selectedFeature = feature;
	// remove any existing popups
	while( map.popups.length ) {
        map.removePopup(map.popups[0]);
	}
	popup = new OpenLayers.Popup.FramedCloud("chicken", 
		feature.geometry.getBounds().getCenterLonLat(),
		null,
		feature.attributes.label,
		null, true, onPopupClose);
	feature.popup = popup;
	popup.minSize = new OpenLayers.Size(200,50);
	popup.maxSize = new OpenLayers.Size(250,200);
	map.addPopup(popup);
}
function onFeatureUnselect(feature) {
	if(feature.popup) {
		map.removePopup(feature.popup);
		feature.popup.destroy();
		delete feature.popup;
	}
}


/**
 * Add markers (vector) to the map.
 * Also removes popups and selects added feature.
 * @param {float} long
 * @param {float} lat
 * @param {featuretype} the type of feature/marker (0=address,1=facility,2=identify)
 * @param {label} the content to put in the popup
 */
function addMarker(lon, lat, featuretype, label) {
	// remove old features of same type
	feats = markerLayer.features;
	for(i = 0; i < feats.length; i++) {
		if (feats[i].attributes.type == featuretype) markerLayer.removeFeatures(feature);
	}
	// Add new feature
	point = new OpenLayers.Geometry.Point(lon, lat);
	OpenLayers.Projection.transform(point, map.displayProjection, map.getProjectionObject());
	label = '<div>' + label + "</div>";
	label += '<br /><div><a href="#" onclick="zoomTo(' + point.x + ', ' + point.y + ', 8); return false">Zoom to Feature</a></div>';
	feature = new OpenLayers.Feature.Vector(point, {type: featuretype, label: label} );
	
	markerLayer.addFeatures(feature);
	// zoom to feature 
	zoomToLonLat (lon, lat, map.getNumZoomLevels() - 3);
	
	// open feature popup if map width greater than 500 pixels (hides on portables)
	if ($("#map").width() > 600 ) selectControl.select(feature);
}


/**
  * Click event handler for the map
  */
OpenLayers.Control.Click = OpenLayers.Class(OpenLayers.Control, {                
	defaultHandlerOptions: {
		'single': true,
		'double': false,
		'pixelTolerance': 0,
		'stopSingle': false,
		'stopDouble': false
	},
	initialize: function(options) {
		this.handlerOptions = OpenLayers.Util.extend(
			{}, this.defaultHandlerOptions
		);
		OpenLayers.Control.prototype.initialize.apply(
			this, arguments
		); 
		this.handler = new OpenLayers.Handler.Click(
			this, {
				'click': this.trigger
			}, this.handlerOptions
		);
	}, 
	trigger: function(e) {
		var lonlat = map.getLonLatFromViewPortPx(e.xy);
		if (map.getScale() < 7000) {
			url = pointOverlay(lonlat.lon, lonlat.lat, 900913, 'tax_parcels', 'pid', "", 'json', '?');
			$.getJSON(url, function(data){
				if (data.total_rows > 0 ) { 
					$.each(data.rows, function(i, item){
						url = wsbase + "v1/ws_mat_pidgeocode.php?format=json&callback=?";
						args = "&pid=" + urlencode(item.row.pid);
						url = url + args;
						$.getJSON(url, function(data) {
							if (data.total_rows > 0 ) {
								if (i == 0) locationFinder("Address", 'master_address_table', 'objectid', data.rows[0].row.objectid);
							}
						});
					}); 
				}
			});
		}
	}
});

